#ifndef NTABLEWIDGET_H
#define NTABLEWIDGET_H
#include <QtWidgets>
#include "tools/Gadget.h"
#include "solar/trunk/NSurveyor.h"
#include "solar/trunk/NinsipidView.h"
#include "tools/Diary.h"

class P_Tabdelegate : public QStyledItemDelegate{

public:
    P_Tabdelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override {
        QStyleOptionViewItem newOption(option);
        newOption.state &= ~QStyle::State_HasFocus;
        /*&= 是位与赋值运算符，它将左侧变量与右侧表达式的结果进行位与操作，并将结果赋值给左侧变量
        ~ 是位取反运算符*/
        QStyledItemDelegate::paint(painter, newOption, index);
    }
};


class SecTabload : public QThread{

    Q_OBJECT

public:

    SecTabload(QMap<ThreadPoint, NT::THREAD_STATE> &_impact_thread_){impact_thread = &_impact_thread_;}

    void setInfo(QMap<QString, QList<QString>> &datas,  int min, int max)
    {
        /******  判断条件为 min不小于0，否则报超索引，并且max不大于最大数据索引，避免数据为空时max超索引。同时保持max > min ******/
        int nsize = datas["reserve-duty-name"].size();
        min >= 0 ? minnum = min : minnum = 0;
        max >= nsize ? maxnum = nsize - 1 : maxnum = max;
        if (maxnum < min) maxnum = max;
        impact_ststr = &datas;
        diary4("min:", min, " max:", max, Diary::Debug)
    }

    std::pair<int, int> range(){
       return std::make_pair(minnum, maxnum);
    }

    void run()
    {
        QList<QString> mdrs_names = (*impact_ststr)["reserve-duty-name"];
        for(int row = minnum; row <= maxnum; row++)
        {
            if ((*impact_thread)[ThreadPoint::MULTI_TABUPDATE] == NT::THREAD_TERMINATED)
            {
                break;
            }
            else if ((*impact_thread)[ThreadPoint::MULTI_TABUPDATE] == NT::THREAD_PAUSE)
            {
                while (true)
                {
                    if ((*impact_thread)[ThreadPoint::MULTI_TABUPDATE] == NT::THREAD_PAUSE)
                    {
                        QThread::msleep(30);
                        continue;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            else
            {
                if (!mdrs_names.isEmpty() && mdrs_names.size() > row)
                {
                emit data_send(row,
                               (*impact_ststr)["reserve-duty-name"][row],
                               (*impact_ststr)["reserve-duty-artist"][row],
                               (*impact_ststr)["reserve-duty-suffix"][row],
                               (*impact_ststr)["reserve-duty-bitrate"][row],
                               (*impact_ststr)["reserve-duty-size"][row],
                               (*impact_ststr)["reserve-duty-duration"][row],
                               (*impact_ststr)["reserve-duty-cover"][row]);
                QThread::msleep(30);
                }
            }
        }
        (*impact_thread)[ThreadPoint::MULTI_TABUPDATE] = NT::THREAD_IDLEABOUT;
        quit();
    }

private:
    int minnum;
    int maxnum;
    QMap<QString, QList<QString>> *impact_ststr;
    QMap<ThreadPoint, NT::THREAD_STATE> *impact_thread;

signals:
    void data_send(int, QString,  QString, QString, QString, QString, QString, QString);
};


class NTableWidget : public QTableWidget{

    Q_OBJECT

public:

    NTableWidget(QWidget *parent=nullptr) : rowc(0), indexof(0){
        setParent(parent);
        descTimer.setInterval(10);
        croll_mach->setFixedSize(60,60);
        croll_mach->doconfigur_textsetting(QFont("KaiTi_GB2312", 35, 60, true));
        croll_mach->doconfigur_color(QColor(95,136,105));
        setVerticalScrollBar(vscroll);
        setItemDelegate(itemdelefate);
        vscroll->d_linear_subcolor({QColor(222,236,221)});
        vscroll->d_linear_addcolor({QColor(222,225,232)});
        connect(&descTimer, &QTimer::timeout, this, &NTableWidget::descReset);
        connect(vscroll, &NScrollBar::slidervalue, this, &NTableWidget::scrollindexof_change);
    }

    ~NTableWidget(){
        delete vscroll;
        delete itemdelefate;
    }

    void setScrollBarWidth(Qt::Orientation orien, int howvalue){
        switch (orien)
        {
            case Qt::Vertical:
                verticalScrollBar()->setStyleSheet(QString("QScrollBar:vertical { width: %1px; }").arg(howvalue));
                break;
            case Qt::Horizontal:
                verticalScrollBar()->setStyleSheet(QString("QScrollBar:vertical { height: %1px; }").arg(howvalue));
                break;
        }
    }

    QList<int> prossRows(bool reverse = false){
        QList<int> rows;
        foreach(QTableWidgetItem *item, selectedItems())
        {
            int index = row(item);
            if (!rows.contains(index)) rows.append(index);
        }
        definfc.orderBy(rows, reverse);
        return rows;
    }

    void descReset()
    {
        if (!descTimer.isActive()) descTimer.start();
        QTableWidgetItem *item = this->item(rowc, 0);
        if (item != NULL) item->setText(QString::number(rowc + 1));
        rowc ++;
        if (rowc == rowCount())
        {
            rowc =0;
            descTimer.stop();
        }
    }

    void setRowCount(int rows){
        QTableWidget::setRowCount(rows);
        vscroll->setMaxHpower(rows);
    }

    void suspendUpdate(){
        vscroll->setValue(vscroll->value());
        diary2("suspend pos num -> ", vscroll->value(), Diary::Warning)
    }

    void clearContents(){
        int maxrow = rowCount();
        int maxcol = columnCount();
        for(int row = 0; row < maxrow; row++)
        {
            for(int col = 0; col < maxcol; col++)
            {
                del(row, -1);
            }
        }
    }

    void del(int row, int column){
        QList<int> columns;
        if (column == -1)
        {
            for(int colum = 0; colum < columnCount(); colum++)
            {
                QWidget *cellwidget = cellWidget(row, colum);
                if (cellwidget) {removeCellWidget(row, colum); delete cellwidget;}
             }
        }
        else
        {
            QWidget *cellwidget = cellWidget(row, column);
            if (cellwidget) {removeCellWidget(row, column); delete cellwidget;}
        }
        if (rowHeight(row)) removeRow(row);
    }

    void del(QTableWidgetItem *item, int column){
        if (item != NULL)
        {
            int row = this->row(item);
            del(row, column);
        }
    }

    uint del(QList<QTableWidgetItem*> datas={}){
        QList<int> rows;
        if (datas.isEmpty()) datas.append(selectedItems());
        foreach(QTableWidgetItem *item, datas) {if (!rows.contains(this->row(item))) rows.append(this->row(item));}
        definfc.orderBy(rows, true);
        foreach(int row, rows) del(row, -1);
        return rows.size();
    }

    uint del(QList<int> datas, bool reverse=false){
        if (reverse)
        {
            QList<int> rows;
            for(int row = 0; row < rowCount(); row++) {if (!datas.contains(row)) rows.append(row);}
            definfc.orderBy(rows, true);
            foreach(int row, rows) del(row, -1);
            return rows.size();
        }
        else
        {
            definfc.orderBy(datas, true);
            foreach(int row, datas) del(row, -1);
            return datas.size();
        }
    }

    void slideTo(){
        /* table item view scroll according to scroll proportion index */
        QModelIndex tablindex = model()->index(indexof, 0);
        scrollTo(tablindex, QAbstractItemView::PositionAtBottom);
    }

    void slideTo(int row){
        QModelIndex tablindex = model()->index(row, 0);
        scrollTo(tablindex, QAbstractItemView::PositionAtBottom);
    }

    void selects(int min, int max)
    {
        setSelectionMode(QAbstractItemView::MultiSelection);
        if (max && min < max)
        {
            for (int row = min; row <= max; row++)
            {
                for (int col = 0; col < columnCount(); col++)
                {
                    QTableWidgetItem *item = this->item(row, col);
                    if (item) item ->setSelected(true);
                }
            }
        }
        setSelectionMode(QAbstractItemView::SingleSelection);
    }

    void selects(QList<int> range)
    {
        setSelectionMode(QAbstractItemView::MultiSelection);
        for (int row : range)
        {
            for (int col = 0; col < columnCount(); col++)
            {
                QTableWidgetItem *item = this->item(row, col);
                if (item) item ->setSelected(true);
            }
        }
        setSelectionMode(QAbstractItemView::SingleSelection);
    }

    void d_avgheight(int avrnum){
        setProperty("avg-row-height", avrnum);
    }

    NScrollBar *vscroll = new NScrollBar(this, NT::ORIEN_VERTICAL);

private:
    int rowc;
    int indexof;
    Extend definfc;
    QTimer descTimer;
    P_Tabdelegate *itemdelefate = new P_Tabdelegate(this);
    NinsipidView *croll_mach = new NinsipidView(this);

    struct info{
        int pre_row;
        int mv_row;
        int avg_h;
        QPoint pre_pos;
        QPoint mv_pos;
    };

    info d_info;

    void mousePressEvent(QMouseEvent *event){
        QTableWidget::mousePressEvent(event);
        d_info.pre_pos = event->pos();
        d_info.pre_row = currentRow();
    }


    void mouseReleaseEvent(QMouseEvent *event){
        QTableWidget::mouseReleaseEvent(event);
        if (!d_info.pre_pos.isNull() &&
           abs(event->pos().y() - d_info.pre_pos.y()) > rowHeight(currentRow()) &&
            d_info.pre_row != d_info.mv_row)
        {
            d_info.pre_row < d_info.mv_row ? emit select_range(d_info.pre_row, d_info.mv_row) :
                                             emit select_range(d_info.mv_row, d_info.pre_row);
        }
        d_info.pre_pos = QPoint();
        d_info.mv_pos = QPoint();
        croll_mach->setVisible(false);
    }


    void mouseMoveEvent(QMouseEvent *event){
        QTableWidget::mouseMoveEvent(event);
        d_info.mv_row = currentRow();
        uint scrollhow = abs(currentRow() - d_info.pre_row);
        croll_mach->doconfigur_text(QString::number(scrollhow + 1));
        if (scrollhow &&
            !d_info.pre_pos.isNull() &&
            !croll_mach->isVisible()) croll_mach->setVisible(true);
    }


    void showEvent(QShowEvent *event){
        QTableWidget::showEvent(event);
        int x = (width() - croll_mach->width()) / 2;
        int y = (height() - croll_mach->height()) / 2;
        croll_mach->move(x, y); qDebug() << x << y << 2;
    }


    void keyPressEvent(QKeyEvent *event){
        int key = event->key();
        if (key == 16777248)
        {
            setSelectionMode(QAbstractItemView::MultiSelection);
        }
        QTableWidget::keyPressEvent(event);
    }


    void keyReleaseEvent(QKeyEvent *event){
        int key = event->key();
        if (key == 16777248)
        {
            setSelectionMode(QAbstractItemView::SingleSelection);
        }
        QTableWidget::keyReleaseEvent(event);
    }


    void scrollindexof_change(double value){
        int minrow = 0;
        int maxrow = rowCount();
        int scrollmax = vscroll->maximum();
        int rowavg = property("avg-row-height").toInt();
        long maxvsb = floor((double)height() / rowavg);
        indexof = ceil(rowCount() * value / scrollmax);
        indexof - maxvsb < 0 ? minrow = indexof : minrow = indexof - maxvsb;
        indexof + maxvsb > rowCount() ? maxrow = rowCount() : maxrow = indexof + maxvsb;
        emit scroll_range(minrow, maxrow); slideTo();
    }


signals:
    void scroll_range(int, int);
    void select_range(int, int);
};

#endif
